home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / gnuchess.lha / nuxdsp.c < prev    next >
C/C++ Source or Header  |  1990-06-09  |  34KB  |  1,606 lines

  1. /* nuxdsp.c - (new)  ALPHA interface for CHESS
  2.  
  3.   Revision: 1990-05-09
  4.  
  5.   Copyright (C) 1986, 1987, 1988, 1989, 1990 Free Software Foundation, Inc.
  6.   Copyright (c) 1988, 1989, 1990  John Stanback
  7.  
  8.   Modified extensively Nov 1989 Christopher North-Keys
  9.     40x24 two-colour display
  10.     option for shading black squares
  11.     expanded game save, list, and restore features using $HOME
  12.     option to disable display of coordinates
  13.     optional auto-updating of positional information
  14.     optional starring of black side
  15.     mass toggle for reverse-video functions
  16.  
  17.   This file is part of CHESS.
  18.  
  19.   CHESS is distributed in the hope that it will be useful, but WITHOUT ANY
  20.   WARRANTY.  No author or distributor accepts responsibility to anyone for
  21.   the consequences of using it or for whether it serves any particular
  22.   purpose or works at all, unless he says so in writing.  Refer to the CHESS
  23.   General Public License for full details.
  24.  
  25.   Everyone is granted permission to copy, modify and redistribute CHESS, but
  26.   only under the conditions described in the CHESS General Public License.
  27.   A copy of this license is supposed to have been given to you along with
  28.   CHESS so you can know your rights and responsibilities.  It should be in a
  29.   file named COPYING.  Among other things, the copyright notice and this
  30.   notice must be preserved on all copies.
  31. */
  32.  
  33.  
  34. #include <ctype.h>
  35. #include <signal.h>
  36. #ifdef MSDOS
  37. #include <dos.h>
  38. #include <conio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <time.h>
  42.  
  43. #define ESC 0x1B
  44. #define scanz scanf
  45. #define printz printf
  46. #define refresh() fflush(stdout)
  47.  
  48. int mycntl1, mycntl2;
  49. static void param (short n);
  50. #else
  51. #include <sys/param.h>
  52. #include <sys/types.h>
  53. #include <sys/file.h>
  54. #include <curses.h>
  55.  
  56. #define scanz fflush(stdout),scanw
  57. #define printz printw
  58.  
  59. /* <stdlib.h> */
  60. extern void *malloc (size_t);
  61. extern void exit (int);
  62. /* <string.h> */
  63. extern char *strcat (char *, const char *);
  64. extern int strcmp (const char *, const char *);
  65. extern char *strcpy (char *, const char *);
  66. /* <time.h> */
  67. extern long int time (long int *);
  68. #endif /* MSDOS */
  69.  
  70. #include "gnuchess.h"
  71.  
  72. #define pxx " PNBRQK"
  73. #define qxx " pnbrqk"
  74. #define rxx "12345678"
  75. #define cxx "abcdefgh"
  76. #define TAB (43)
  77. /* coordinates within a square for the following are ([1,5],[1,3]) */
  78. #define SQW (5)
  79. #define SQH (3)
  80. #define VIR_C(s)  ((flag.reverse) ? 7-column(s) : column(s))
  81. #define VIR_R(s)  ((flag.reverse) ? 7-row(s) : row(s))
  82. #define VSQ_X(x)  ((flag.reverse) ? SQW + 1 - (x) : (x))
  83. #define VSQ_Y(y)  ((flag.reverse) ? SQH + 1 - (y) : (y))
  84. #define Vblack(s) (!((VIR_C(s) + VIR_R(s)) % 2))
  85. /* Squares swapped */
  86. #define Vcoord(s,x,y) \
  87.     ((SQW)*(VIR_C(s)))+(x),((SQH)*(7-VIR_R(s))+(y))
  88. /* Squares and internal locations swapped */
  89. #define VcoordI(s,x,y) \
  90.     ((SQW)*(VIR_C(s)))+(VSQ_X(x)),((SQH)*(7-VIR_R(s))+(VSQ_Y(y)))
  91. /* Squares and internal rows swapped */
  92. #define VcoordR(s,x,y) \
  93.     ((SQW)*(VIR_C(s)))+(x),((SQH)*(7-VIR_R(s))+(VSQ_Y(y)))
  94.  
  95. static char mvstr[4][6];
  96. static char* ColorStr[2] = {"White", "Black"};
  97. static long evrate;
  98. short PositionFlag = 0;
  99. short coords = 1;
  100. #if defined(MSDOS) && !defined(SEVENBIT)
  101. short rv = 0;
  102. static void ONormal (void);
  103. static void OReverse (void);
  104. #else
  105. short stars = 0;
  106. short rv = 1;
  107. short shade = 0;
  108. #endif /* MSDOS && !SEVENBIT */
  109.  
  110. extern char *getenv (const char *);
  111. void TerminateSearch (int), Die (int);
  112.  
  113. void
  114. Initialize (void)
  115. {
  116.   signal (SIGINT, Die);
  117. #ifndef MSDOS
  118.   signal (SIGQUIT, Die);
  119.   initscr ();
  120.   crmode ();
  121. #else
  122.   mycntl1 = mycntl2 = 0;
  123. #endif /* MSDOS */
  124. }
  125.  
  126. void
  127. ExitChess (void)
  128. {
  129.   ListGame ();
  130.   gotoXY (1, 24);
  131. #ifndef MSDOS
  132.   nocrmode ();
  133.   endwin ();
  134. #endif /* MSDOS */
  135.   exit (0);
  136. }
  137.  
  138. void
  139. Die (int Sig)
  140. {
  141.   char s[80];
  142.  
  143.   signal (SIGINT, SIG_IGN);
  144. #ifdef MSDOS
  145.   Sig++;                /* shut up the compiler */
  146. #else
  147.   signal (SIGQUIT, SIG_IGN);
  148. #endif /* MSDOS */
  149.   ShowMessage ("Abort? ");
  150.   scanz ("%s", s);
  151.   if (strcmp (s, "yes") == 0)
  152.     ExitChess ();
  153.   signal (SIGINT, Die);
  154. #ifndef MSDOS
  155.   signal (SIGQUIT, Die);
  156. #endif /* MSDOS */
  157. }
  158.  
  159. void
  160. TerminateSearch (int Sig)
  161. {
  162.   signal (SIGINT, SIG_IGN);
  163. #ifdef MSDOS
  164.   Sig++;                /* shut up the compiler */
  165. #else
  166.   signal (SIGQUIT, SIG_IGN);
  167. #endif /* MSDOS */
  168.   flag.timeout = true;
  169.   flag.bothsides = false;
  170.   signal (SIGINT, Die);
  171. #ifndef MSDOS
  172.   signal (SIGQUIT, Die);
  173. #endif /* MSDOS */
  174. }
  175.  
  176. void
  177. algbr (short int f, short int t, short int flag)
  178.  
  179. /*
  180.    Generate move strings in different formats.
  181. */
  182.  
  183. {
  184.   int m3p;
  185.  
  186.   if (f != t)
  187.     {
  188.       /* algebraic notation */
  189.       mvstr[0][0] = cxx[column (f)];
  190.       mvstr[0][1] = rxx[row (f)];
  191.       mvstr[0][2] = cxx[column (t)];
  192.       mvstr[0][3] = rxx[row (t)];
  193.       mvstr[0][4] = mvstr[3][0] = '\0';
  194.       if ((mvstr[1][0] = pxx[board[f]]) == 'P')
  195.     {
  196.       if (mvstr[0][0] == mvstr[0][2])    /* pawn did not eat */
  197.         {
  198.           mvstr[2][0] = mvstr[1][0] = mvstr[0][2];    /* to column */
  199.           mvstr[2][1] = mvstr[1][1] = mvstr[0][3];    /* to row */
  200.           m3p = 2;
  201.         }
  202.       else
  203.         /* pawn ate */
  204.         {
  205.           mvstr[2][0] = mvstr[1][0] = mvstr[0][0];    /* from column */
  206.           mvstr[2][1] = mvstr[1][1] = mvstr[0][2];    /* to column */
  207.           mvstr[2][2] = mvstr[0][3];
  208.           m3p = 3;        /* to row */
  209.         }
  210.       mvstr[2][m3p] = mvstr[1][2] = '\0';
  211.       if (flag & promote)
  212.         {
  213.           mvstr[0][4] = mvstr[1][2] = mvstr[2][m3p] = qxx[flag & pmask];
  214.           mvstr[1][3] = mvstr[2][m3p + 1] = mvstr[0][5] = '\0';
  215.         }
  216.     }
  217.       else
  218.     /* not a pawn */
  219.     {
  220.       mvstr[2][0] = mvstr[1][0];
  221.       mvstr[2][1] = mvstr[0][1];
  222.       mvstr[2][2] = mvstr[1][1] = mvstr[0][2];    /* to column */
  223.       mvstr[2][3] = mvstr[1][2] = mvstr[0][3];    /* to row */
  224.       mvstr[2][4] = mvstr[1][3] = '\0';
  225.       strcpy (mvstr[3], mvstr[2]);
  226.       mvstr[3][1] = mvstr[0][0];
  227.       if (flag & cstlmask)
  228.         {
  229.           if (t > f)
  230.         {
  231.           strcpy (mvstr[1], "o-o");
  232.           strcpy (mvstr[2], "O-O");
  233.         }
  234.           else
  235.         {
  236.           strcpy (mvstr[1], "o-o-o");
  237.           strcpy (mvstr[2], "O-O-O");
  238.         }
  239.         }
  240.     }
  241.     }
  242.   else
  243.     mvstr[0][0] = mvstr[1][0] = mvstr[2][0] = mvstr[3][0] = '\0';
  244. }
  245.  
  246. int
  247. VerifyMove (char *s, short int iop, short unsigned int *mv)
  248.  
  249. /*
  250.    Compare the string 's' to the list of legal moves available for the
  251.    opponent. If a match is found, make the move on the board.
  252. */
  253.  
  254. {
  255.   static short pnt, tempb, tempc, tempsf, tempst, cnt;
  256.   static struct leaf xnode;
  257.   struct leaf *node;
  258.  
  259.   *mv = 0;
  260.   if (iop == 2)
  261.     {
  262.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  263.       return (false);
  264.     }
  265.   cnt = 0;
  266.   MoveList (opponent, 2);
  267.   pnt = TrPnt[2];
  268.   while (pnt < TrPnt[3])
  269.     {
  270.       node = &Tree[pnt++];
  271.       algbr (node->f, node->t, (short) node->flags);
  272.       if (strcmp (s, mvstr[0]) == 0 || strcmp (s, mvstr[1]) == 0 ||
  273.       strcmp (s, mvstr[2]) == 0 || strcmp (s, mvstr[3]) == 0)
  274.     {
  275.       cnt++;
  276.       xnode = *node;
  277.     }
  278.     }
  279.   if (cnt == 1)
  280.     {
  281.       MakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst, &INCscore);
  282.       if (SqAtakd (PieceList[opponent][0], computer))
  283.     {
  284.       UnmakeMove (opponent, &xnode, &tempb, &tempc, &tempsf, &tempst);
  285.       ShowMessage ("Illegal Move!!");
  286.       return (false);
  287.     }
  288.       else
  289.     {
  290.       if (iop == 1)
  291.         return (true);
  292.       UpdateDisplay (xnode.f, xnode.t, 0, (short) xnode.flags);
  293.       if ((board[xnode.t] == pawn)
  294.           || (xnode.flags & capture)
  295.           || (xnode.flags & cstlmask))
  296.         {
  297.           Game50 = GameCnt;
  298.           ZeroRPT ();
  299.         }
  300.       GameList[GameCnt].depth = GameList[GameCnt].score = 0;
  301.       GameList[GameCnt].nodes = 0;
  302.       ElapsedTime (1);
  303.       GameList[GameCnt].time = (short) et;
  304.       TimeControl.clock[opponent] -= et;
  305.       --TimeControl.moves[opponent];
  306.       *mv = (xnode.f << 8) | xnode.t;
  307.       algbr (xnode.f, xnode.t, false);
  308.       return (true);
  309.     }
  310.     }
  311.   if (cnt > 1)
  312.     ShowMessage ("Ambiguous Move!");
  313.   return (false);
  314. }
  315.  
  316. void
  317. help (void)
  318. {
  319.   ClrScreen ();
  320.   printz ("CHESS command summary\n");
  321.   printz ("g1f3     move from g1 to f3      quit      Exit Chess\n");
  322.   printz ("Nf3      move knight to f3       beep      on/off\n");
  323.   printz ("o-o      castle king side        easy      on/off\n");
  324.   printz ("o-o-o    castle queen side       hash      on/off\n");
  325.   printz ("bd       redraw board            reverse   board display\n");
  326.   printz ("list     game to chess.lst       book      on/off\n");
  327.   printz ("undo     undo last ply           remove    take back a move\n");
  328.   printz ("edit     edit board              force     enter game moves\n");
  329.   printz ("switch   sides with computer     both      computer match\n");
  330.   printz ("white    computer plays white    black     computer plays black\n");
  331.   printz ("depth    set search depth        level     select level\n");
  332.   printz ("post     principle variation     hint      suggest a move\n");
  333.   printz ("save     game to file            get       game from file\n");
  334.   printz ("random   randomize play          new       start new game\n");
  335.   printz ("rv       toggle reverse video    coords    toggle coords\n");
  336. #if !defined(MSDOS) || defined(SEVENBIT)
  337.   printz ("shade    toggle shade black      stars     toggle stars\n");
  338. #endif /* !MSDOS || SEVENBIT */
  339.   printz ("p        show coordinate values\n");
  340.   gotoXY (10, 21);
  341.   printz ("Computer: %s", ColorStr[computer]);
  342.   gotoXY (10, 22);
  343.   printz ("Opponent: %s", ColorStr[opponent]);
  344.   gotoXY (10, 23);
  345.   printz ("Level: %ld", Level);
  346.   gotoXY (10, 24);
  347.   printz ("Easy mode: %s", (flag.easy) ? "ON" : "OFF");
  348.   gotoXY (40, 21);
  349.   printz ("Depth: %d", MaxSearchDepth);
  350.   gotoXY (40, 22);
  351.   printz ("Random: %s", (dither) ? "ON" : "OFF");
  352.   gotoXY (40, 23);
  353.   printz ("Transposition table: %s", (flag.hash) ? "ON" : "OFF");
  354.   gotoXY (40, 24);
  355.   printz ("Hit <RET> to return: ");
  356.   refresh ();
  357.   fflush(stdin);
  358.   getchar();
  359.   ClrScreen ();
  360.   UpdateDisplay (0, 0, 1, 0);
  361. }
  362.  
  363. void
  364. EditBoard (void)
  365.  
  366. /*
  367.   Set up a board position. Pieces are entered by typing the piece
  368.   followed by the location. For example, Nf3 will place a knight on
  369.   square f3.
  370. */
  371.  
  372. {
  373.   short a, r, c, sq, i;
  374.   char s[80];
  375.  
  376.   ClrScreen ();
  377.   UpdateDisplay (0, 0, 1, 0);
  378.   gotoXY (TAB, 3);
  379.   printz (".   Exit to main");
  380.   gotoXY (TAB, 4);
  381.   printz ("#   Clear board");
  382.   gotoXY (TAB, 5);
  383.   printz ("c   Change sides");
  384.   gotoXY (TAB, 7);
  385.   printz ("Enter piece & location: ");
  386.   a = white;
  387.   do
  388.     {
  389.       gotoXY (TAB, 6);
  390.       printz ("Editing: %s", ColorStr[a]);
  391.       gotoXY (TAB + 24, 7);
  392.       ClrEoln ();
  393.       scanz ("%s", s);
  394.       if (s[0] == '#')
  395.     {
  396.       for(sq = 0; sq < 64; sq++)
  397.         {
  398.           board[sq] = no_piece;
  399.           color[sq] = neutral;
  400.           DrawPiece (sq);
  401.         }
  402.     }
  403.       if (s[0] == 'c' || s[0] == 'C')
  404.     a = otherside[a];
  405.       c = s[1] - 'a';
  406.       r = s[2] - '1';
  407.       if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8))
  408.     {
  409.       sq = locn (r, c);
  410.       for (i = king; i > no_piece; i--)
  411.         if ((s[0] == pxx[i]) || (s[0] == qxx[i]))
  412.           break;
  413.       board[sq] = i;
  414.       color[sq] = (board[sq] == no_piece) ? neutral : a;    
  415.       DrawPiece (sq);
  416.     }
  417.   } while (s[0] != '.');
  418.  
  419.   for (sq = 0; sq < 64; sq++)
  420.     Mvboard[sq] = (board[sq] != Stboard[sq]) ? 10 : 0;
  421.   GameCnt = 0;
  422.   Game50 = 1;
  423.   ZeroRPT ();
  424.   Sdepth = 0;
  425.   InitializeStats ();
  426.   ClrScreen ();
  427.   UpdateDisplay (0, 0, 1, 0);
  428. }
  429.  
  430. void
  431. ShowPlayers (void)
  432. {      
  433.   gotoXY (TAB, ((flag.reverse) ? 23 : 2));
  434.   printz ("%s", (computer == black) ? "Computer" : "Human   ");
  435.   gotoXY (TAB, ((flag.reverse) ? 2 : 23));
  436.   printz ("%s", (computer == white) ? "Computer" : "Human   ");
  437. }
  438.  
  439. void
  440. ShowDepth (char ch)
  441. {
  442.   gotoXY (TAB, 4);
  443.   printz ("Depth= %d%c ", Sdepth, ch);
  444.   ClrEoln ();
  445. }
  446.  
  447. void
  448. ShowScore (short score)
  449. {
  450.   gotoXY (TAB, 5);
  451.   printz ("Score= %d", score);
  452.   ClrEoln ();
  453. }
  454.  
  455. void
  456. ShowMessage (char *s)
  457. {
  458.   gotoXY (TAB, 6);
  459.   printz ("%s", s);
  460.   ClrEoln ();
  461. }
  462.  
  463. void
  464. ClearMessage (void)
  465. {
  466.   gotoXY (TAB, 6);
  467.   ClrEoln ();
  468. }
  469.  
  470. void
  471. ShowCurrentMove (short int pnt, short int f, short int t)
  472. {
  473.   algbr (f, t, false);
  474.   gotoXY (TAB, 7);
  475.   printz ("(%2d) %4s", pnt, mvstr[0]);
  476. }
  477.  
  478. void
  479. ShowHeader (void)
  480. {
  481.   gotoXY (TAB, 10);
  482. #ifdef MSDOS
  483.   printz ("GNU Chess display (MS-DOS, Mar 90)");
  484. #else
  485.   printz ("GNU Chess display (Nov 89)");
  486. #endif /* MSDOS */
  487. }
  488.  
  489. void
  490. ShowSidetomove (void)
  491. {
  492.   gotoXY (TAB, 14);
  493.   printz ("%2d:   %s", 1 + GameCnt / 2, ColorStr[player]);
  494.   ClrEoln ();
  495. }
  496.  
  497. void
  498. ShowPrompt (void)
  499. {
  500.   gotoXY (TAB, 19);
  501.   printz ("Your move is? ");
  502.   ClrEoln ();
  503. }
  504.  
  505. void
  506. ShowNodeCnt (long int NodeCnt, long int evrate)
  507. {      
  508.   gotoXY (TAB, 21);
  509.   printz ("Nodes= %8ld, Nodes/Sec= %5ld", NodeCnt, evrate);
  510.   ClrEoln ();
  511. }  
  512.  
  513. void
  514. ShowResults (short int score, short unsigned int *bstline, char ch)
  515. {
  516.   unsigned char d, ply;
  517.   if (flag.post)
  518.     {
  519.       ShowDepth (ch);
  520.       ShowScore (score);
  521.       d = 7;
  522.       for (ply = 1; bstline[ply] > 0; ply++)
  523.     {
  524.       if (ply % 4 == 1)
  525.         {
  526.           gotoXY (TAB, ++d);
  527.           ClrEoln ();
  528.         }
  529.       algbr ((short) bstline[ply] >> 8, (short) bstline[ply] & 0xFF, false);
  530.       printz ("%5s ", mvstr[0]);
  531.     }
  532.       ClrEoln ();    
  533.       while (d < 13)
  534.     {
  535.       gotoXY (TAB, ++d);
  536.       ClrEoln ();
  537.     }
  538.     }
  539. }
  540.  
  541. void
  542. SearchStartStuff (short int side)
  543. {
  544.   short i;
  545.   
  546.   signal (SIGINT, TerminateSearch);
  547. #ifdef MSDOS
  548.   side++;                /* shut up the compiler */
  549. #else
  550.   signal (SIGQUIT, TerminateSearch);
  551. #endif /* MSDOS */
  552.   for (i = 4; i < 14; i++)
  553.     {
  554.       gotoXY (TAB, i);
  555.       ClrEoln ();
  556.     }
  557. }
  558.  
  559. void
  560. OutputMove (void)
  561. {
  562.   int i;
  563.  
  564.   UpdateDisplay (root->f, root->t, 0, (short) root->flags);
  565.   gotoXY (TAB, 17);
  566.   printz ("My move is: %s", mvstr[0]);
  567.   if (flag.beep)
  568.     putchar (7);
  569.   ClrEoln ();
  570.  
  571.   gotoXY (TAB, 24);
  572.   if (root->flags & draw)
  573.     printz ("Drawn game!");
  574.   else if (root->score == -9999)
  575.     printz ("Opponent mates!");
  576.   else if (root->score == 9998)
  577.     printz ("Computer mates!");
  578.   else if (root->score < -9000)
  579.     printz ("Opponent will soon mate!");
  580.   else if (root->score > 9000)
  581.     printz ("Computer will soon mate!");
  582.   ClrEoln ();
  583.  
  584.   if (flag.post)
  585.     {
  586.       ShowNodeCnt (NodeCnt, evrate);
  587.       gotoXY (TAB, 22);
  588.       for (i = 1999; i >= 0 && Tree[i].f == 0 && Tree[i].t == 0; i--);
  589.       printz ("Max Tree= %5d", i);
  590.       ClrEoln ();
  591.     }
  592. }
  593.  
  594. void
  595. ElapsedTime (short int iop)
  596.  
  597. /*
  598.   Determine the time that has passed since the search was started. If
  599.   the elapsed time exceeds the target (ResponseTime+ExtraTime) then set
  600.   timeout to true which will terminate the search.
  601. */
  602.  
  603. {
  604.   et = time ((long *) 0) - time0;
  605.   if (et < 0)
  606.     et = 0;
  607.   ETnodes += 50;
  608.   if (et > et0 || iop == 1)
  609.     {
  610.       if (et > ResponseTime + ExtraTime && Sdepth > 1)
  611.     flag.timeout = true;
  612.       et0 = et;
  613.       if (iop == 1)
  614.     {
  615.       time0 = time ((long *) 0);
  616.       et0 = 0;
  617.     }
  618.       if (et > 0)
  619.     /* evrate used to be Nodes / cputime I dont` know why */
  620.     evrate = NodeCnt / (et + ft);
  621.       else
  622.     evrate = 0;
  623.       ETnodes = NodeCnt + 50;
  624.       UpdateClocks ();
  625.     }
  626. }
  627.  
  628. void
  629. UpdateClocks (void)
  630. {
  631.   short m, s;
  632.   m = (short) (et / 60);
  633.   s = (short) (et - 60 * (long) m);
  634.   if (TCflag)
  635.     {
  636.       m = (short) ((TimeControl.clock[player] - et) / 60);
  637.       s = (short) (TimeControl.clock[player] - et - 60 * (long) m);
  638.     }
  639.   if (m < 0)
  640.     m = 0;
  641.   if (s < 0)
  642.     s = 0;
  643.   if (player == white)
  644.     gotoXY (60, (flag.reverse) ? 2 : 23);
  645.   else
  646.     gotoXY (60, (flag.reverse) ? 23 : 2);
  647.   printz ("%d:%2d   ", m, s);
  648.   if (flag.post)
  649.     ShowNodeCnt (NodeCnt, evrate);
  650.   refresh ();
  651. }
  652.  
  653.  
  654. void
  655. SetTimeControl (void)
  656. {
  657.   if (TCflag)
  658.     {
  659.       TimeControl.moves[white] = TimeControl.moves[black] = TCmoves;
  660.       TimeControl.clock[white] = TimeControl.clock[black] = 60 * (long) TCminutes;
  661.     }
  662.   else
  663.     {
  664.       TimeControl.moves[white] = TimeControl.moves[black] = 0;
  665.       TimeControl.clock[white] = TimeControl.clock[black] = 0;
  666.       Level = 60 * (long) TCminutes;
  667.     }
  668.   et = 0;
  669.   ElapsedTime (1);
  670. }
  671.  
  672. void
  673. gotoXY (short int x, short int y)
  674. {
  675. #ifdef MSDOS
  676.   putchar(ESC);
  677.   putchar('[');
  678.   param(y);
  679.   putchar(';');
  680.   param(x);
  681.   putchar('H');
  682. #else
  683.   move (y - 1, x - 1);
  684. #endif /* MSDOS */
  685. }
  686.  
  687. void
  688. ClrScreen (void)
  689. {
  690. #ifdef MSDOS
  691.   putchar(ESC);
  692.   putchar('[');
  693.   putchar('2');
  694.   putchar('J');
  695. #else
  696.   clear ();
  697. #endif /* MSDOS */
  698.   refresh ();
  699. }
  700.  
  701. void
  702. ClrEoln (void)
  703. {
  704. #ifdef MSDOS
  705.   putchar(ESC);
  706.   putchar('[');
  707.   putchar('K');
  708. #else
  709.   clrtoeol ();
  710. #endif /* MSDOS */
  711.   refresh ();
  712. }
  713.  
  714. #ifdef MSDOS
  715. void
  716. param(short n)
  717. {
  718.   if (n >= 10)
  719.     {
  720.     register short d, q;
  721.     q = n/10; d = n%10;
  722.     putchar(q + '0');
  723.     putchar(d + '0');
  724.   }
  725.   else
  726.     putchar(n + '0');
  727. }
  728. #endif /* MSDOS */
  729.  
  730. void
  731. OReverse()
  732. {
  733. #ifdef MSDOS
  734.   putchar (ESC);
  735.   putchar ('[');
  736.   param (7);
  737.   putchar ('m');
  738. #else
  739.   standout ();
  740. /* attron (A_REVERSE); */
  741. #endif /* MSDOS */
  742. }
  743.  
  744. void
  745. ONormal()
  746. {
  747. #ifdef MSDOS
  748.   putchar (ESC);
  749.   putchar ('[');
  750.   param (0);
  751.   putchar ('m');
  752. #else
  753.   standend ();
  754. /* attroff (A_REVERSE);*/
  755. #endif /* MSDOS */
  756. }
  757.  
  758. void
  759. DrawPiece (short int sq)
  760. {
  761.   gotoXY (VcoordR (sq, 2, 2));
  762.  
  763.   switch (color[sq])
  764.     {
  765.     case black:
  766.       if (rv)
  767.     OReverse ();
  768. #if defined(MSDOS) && !defined(SEVENBIT)
  769.       printz (" %c ", pxx[board[sq]]);
  770. #else
  771.       printz ((stars ? "*%c*" : " %c "), pxx[board[sq]]);
  772. #endif /* MSDOS && !SEVENBIT */
  773.       ONormal ();
  774.       break;
  775.     case neutral:
  776. #if defined(MSDOS) && !defined(SEVENBIT)
  777.       if (rv)
  778.         printz (Vblack (sq) ? "\262\262\262" : "\260\260\260");
  779.       else
  780.         printz (Vblack (sq) ? "\260\260\260" : "\262\262\262");
  781. #else
  782.       if (shade)
  783.     printz (Vblack (sq) ? "///" : "   ");
  784.       else
  785.     {
  786.       if (Vblack (sq))
  787.         OReverse ();
  788.       printz ("   ");
  789.       ONormal ();
  790.     }
  791. #endif /* MSDOS && !SEVENBIT */
  792.       break;
  793.     case white:
  794. #if defined(MSDOS) && !defined(SEVENBIT)
  795.       if (!rv)
  796.     OReverse ();
  797.       printz (" %c ", pxx[board[sq]]);
  798.       ONormal ();
  799. #else
  800.       printz (" %c ", pxx[board[sq]]);
  801. #endif /* MSDOS && !SEVENBIT */
  802.       break;
  803.     default:
  804.       ShowMessage ("DrawPiece:  color[sq] err");
  805.       break;
  806.     }
  807. }
  808.  
  809. void
  810. DrawSquare (short int sq)
  811. {
  812. #if defined(MSDOS) && !defined(SEVENBIT)
  813.   if (rv)
  814.     {
  815.       gotoXY (Vcoord (sq, 1, 1));
  816.       printz (Vblack (sq) ? "\262\262\262\262\262" : "\260\260\260\260\260");
  817.       gotoXY (Vcoord (sq, 1, 2));
  818.       printz (Vblack (sq) ? "\262\262\262\262\262" : "\260\260\260\260\260");
  819.       gotoXY (Vcoord (sq, 1, 3));
  820.       printz (Vblack (sq) ? "\262\262\262\262\262" : "\260\260\260\260\260");
  821.     }
  822.   else
  823.     {
  824.       gotoXY (Vcoord (sq, 1, 1));
  825.       printz (Vblack (sq) ? "\260\260\260\260\260" : "\262\262\262\262\262");
  826.       gotoXY (Vcoord (sq, 1, 2));
  827.       printz (Vblack (sq) ? "\260\260\260\260\260" : "\262\262\262\262\262");
  828.       gotoXY (Vcoord (sq, 1, 3));
  829.       printz (Vblack (sq) ? "\260\260\260\260\260" : "\262\262\262\262\262");
  830.     }
  831. #else
  832.   if (shade)
  833.     {
  834.       gotoXY (Vcoord (sq, 1, 1));
  835.       printz (Vblack (sq) ? "/////" : "     ");
  836.       gotoXY (Vcoord (sq, 1, 2));
  837.       printz (Vblack (sq) ? "/////" : "     ");
  838.       gotoXY (Vcoord (sq, 1, 3));
  839.       printz (Vblack (sq) ? "/////" : "     ");
  840.     }
  841.   else
  842.     {
  843.       if (Vblack (sq))
  844.     OReverse ();
  845.       gotoXY (Vcoord (sq, 1, 1));
  846.       printz ("     ");
  847.       gotoXY (Vcoord (sq, 1, 2));
  848.       printz ("     ");
  849.       gotoXY (Vcoord (sq, 1, 3));
  850.       printz ("     ");
  851.       ONormal ();
  852.     }
  853. #endif /* MSDOS && !SEVENBIT */
  854. }
  855.  
  856. void
  857. DrawCoords (void)
  858. {
  859.   short z;
  860.  
  861.   for (z = 0; z <= 7; z++)
  862.     {
  863.       short sq;
  864.  
  865.       sq = z << 3;
  866.       gotoXY (VcoordI (sq, 1, 1));
  867. #if !defined(MSDOS) || defined(SEVENBIT)
  868.       if ((Vblack (sq) || shade) && rv)
  869. #endif /* !MSDOS || SEVENBIT */
  870.     OReverse ();
  871.       printz ("%d", 1 + z);
  872.       ONormal ();
  873.     }
  874.  
  875.   for (z = 0; z <= 7; z++)
  876.     {
  877.       short sq;
  878.  
  879.       sq = z;
  880.       gotoXY (VcoordI (sq, SQW, SQH));
  881. #if !defined(MSDOS) || defined(SEVENBIT)
  882.       if ((Vblack (sq) || shade) && rv)
  883. #endif /* !MSDOS || SEVENBIT */
  884.     OReverse ();
  885.       printz ("%c", cxx[z]);
  886.       ONormal ();
  887.     }
  888.  
  889. #if !defined(MSDOS) || defined(SEVENBIT)
  890.   for (z = 1; z <= (8 * SQH); z++)
  891.     {
  892.       gotoXY ((8 * SQW) + 1, z);
  893.       printz ("|");
  894.     }
  895. #endif /* MSDOS && !SEVENBIT */
  896. }
  897.  
  898. void
  899. ShowPostnValue (short int sq)
  900.  
  901. /*
  902.   must have called ExaminePosition() first
  903. */
  904.      
  905. {
  906.   short score;
  907.   
  908.   gotoXY (VcoordR (sq, 2, 1));
  909.   ScorePosition (color[sq], &score);
  910. #if !defined(MSDOS) || defined(SEVENBIT)
  911.   if (Vblack (sq) && !shade)
  912.     OReverse ();
  913. #endif /* !MSDOS || SEVENBIT */
  914.  
  915.   if (color[sq] != neutral)
  916.     printz ("%3d", svalue[sq]);
  917.   else
  918. #if defined(MSDOS) && !defined(SEVENBIT)
  919.     {
  920.       if (rv)
  921.          printz (Vblack (sq) ? "\262\262\262" : "\260\260\260");
  922.       else
  923.         printz (Vblack (sq) ? "\260\260\260" : "\262\262\262");
  924.     }
  925. #else
  926.     printz (shade && Vblack (sq) ? "///" : "   ");
  927. #endif /* MSDOS && !SEVENBIT */
  928.   ONormal ();
  929. }
  930.  
  931. void
  932. ShowPostnValues (void)
  933. {
  934.   short sq, score;
  935.  
  936.   ExaminePosition ();
  937.   for (sq = 0; sq < 64; sq++)
  938.     ShowPostnValue (sq);
  939.   ScorePosition (opponent, &score);
  940.   ShowScore (score);
  941. }
  942.  
  943. void
  944. UpdateDisplay (short int f, short int t, short int redraw, short int isspec)
  945. {
  946.   short sq;
  947.   
  948.   if (redraw)
  949.     {
  950.       ShowHeader ();
  951.       ShowPlayers ();
  952.       for (sq = 0; sq < 64; sq++)
  953.     {
  954.       DrawSquare (sq);
  955.       DrawPiece (sq);
  956.     }
  957.       if (coords)
  958.     DrawCoords ();
  959.     }
  960.   else
  961.     {
  962.       DrawPiece (f);
  963.       DrawPiece (t);
  964.       if (isspec & cstlmask)
  965.     if (t > f)
  966.       {
  967.         DrawPiece (f + 3);
  968.         DrawPiece (t - 1);
  969.       }
  970.     else
  971.       {
  972.         DrawPiece (f - 4);
  973.         DrawPiece (t + 1);
  974.       }
  975.       else if (isspec & epmask)
  976.     {
  977.       DrawPiece (t - 8);
  978.       DrawPiece (t + 8);
  979.     }
  980.     }
  981.   if (PositionFlag)
  982.     ShowPostnValues ();
  983.   refresh ();
  984. }
  985.  
  986. void
  987. GetGame (void)
  988. {
  989.   FILE *fd;
  990.   char fname[256], tname[256];
  991.   char *tmp;
  992.   int c;
  993.   short sq;
  994.   unsigned short m;
  995.  
  996.   tname[0] = 0;
  997.  
  998.   if (tmp = getenv ("HOME"))
  999.     strcpy (fname, tmp);
  1000.   else
  1001.     fname[0] = '\0';
  1002.   strcat (fname, "/");
  1003.  
  1004.   ShowMessage ("File name: ");
  1005.   scanz ("%s", tname);
  1006.  
  1007.   if (tname[0])
  1008.     strcat (fname, tname);
  1009.   else
  1010.     strcat (fname, "chess.000");
  1011.  
  1012.   ShowMessage("Loading ");
  1013.   printz ("%s", fname);
  1014.  
  1015.   if ((fd = fopen (fname, "r")) == NULL)
  1016.     {
  1017.       ShowMessage ("Load failed");
  1018.       return;
  1019.     }
  1020.  
  1021.   fscanf (fd, "%hd%hd%hd", &computer, &opponent, &Game50);
  1022.   fscanf (fd, "%hd%hd", &castld[white], &castld[black]);
  1023.   fscanf (fd, "%hd%hd", &TCflag, &OperatorTime);
  1024.   fscanf (fd, "%ld%ld%hd%hd",
  1025.       &TimeControl.clock[white], &TimeControl.clock[black],
  1026.       &TimeControl.moves[white], &TimeControl.moves[black]);
  1027.   for (sq = 0; sq < 64; sq++)
  1028.     {
  1029.       fscanf (fd, "%hd%hd", &m, &Mvboard[sq]);
  1030.       board[sq] = (m >> 8);
  1031.       color[sq] = (m & 0xFF);
  1032.       if (color[sq] == 0)
  1033.     color[sq] = neutral;
  1034.       else
  1035.     --color[sq];
  1036.     }
  1037.   GameCnt = 0;
  1038.   c = '?';
  1039.   while (c != EOF)
  1040.     {
  1041.       ++GameCnt;
  1042.       c = fscanf (fd, "%hd%hd%hd%ld%hd%hd%hd", &GameList[GameCnt].gmove,
  1043.           &GameList[GameCnt].score, &GameList[GameCnt].depth,
  1044.           &GameList[GameCnt].nodes, &GameList[GameCnt].time,
  1045.           &GameList[GameCnt].piece, &GameList[GameCnt].color);
  1046.       if (GameList[GameCnt].color == 0)
  1047.     GameList[GameCnt].color = neutral;
  1048.       else
  1049.     --GameList[GameCnt].color;
  1050.     }
  1051.   GameCnt--;
  1052.   if (TimeControl.clock[white] > 0)
  1053.     TCflag = true;
  1054.   computer--;
  1055.   opponent--;
  1056.  
  1057.   fclose (fd);
  1058.  
  1059.   InitializeStats ();
  1060.   Sdepth = 0;
  1061.   ShowMessage ("Load done.  Press <Ret>");
  1062.   fflush (stdin);
  1063.   getchar ();
  1064.   UpdateDisplay (0, 0, 1, 0);
  1065.  
  1066. }
  1067.  
  1068. void
  1069. SaveGame (void)
  1070. {
  1071.   FILE *fd;
  1072.   char fname[256], tname[256];
  1073.   char *tmp;
  1074.   short sq, i, c;
  1075.  
  1076.   tname[0] = 0;
  1077.  
  1078.   if (tmp = getenv ("HOME"))
  1079.     strcpy (fname, tmp);
  1080.   else
  1081.     fname[0] = '\0';
  1082.   strcat (fname, "/");
  1083.  
  1084.   ShowMessage ("File name: ");
  1085.   refresh ();
  1086.   scanz ("%s", tname);
  1087.  
  1088.   if (tname[0])
  1089.     strcat (fname, tname);
  1090.   else
  1091.     strcat (fname, "chess.000");
  1092.  
  1093.   ShowMessage("Saving ");
  1094.   printz ("%s", fname);
  1095.  
  1096.   if (NULL == (fd = fopen (fname, "w")))
  1097.     {
  1098.       ShowMessage ("Not saved");
  1099.       return;
  1100.     }
  1101.  
  1102.   fprintf (fd, "%d %d %d\n", computer + 1, opponent + 1, Game50);
  1103.   fprintf (fd, "%d %d\n", castld[white], castld[black]);
  1104.   fprintf (fd, "%d %d\n", TCflag, OperatorTime);
  1105.   fprintf (fd, "%ld %ld %d %d\n",
  1106.        TimeControl.clock[white], TimeControl.clock[black],
  1107.        TimeControl.moves[white], TimeControl.moves[black]);
  1108.   for (sq = 0; sq < 64; sq++)
  1109.     {
  1110.       if (color[sq] == neutral)
  1111.     c = 0;
  1112.       else
  1113.     c = color[sq] + 1;
  1114.       fprintf (fd, "%d %d\n", 256 * board[sq] + c, Mvboard[sq]);
  1115.     }
  1116.   for (i = 1; i <= GameCnt; i++)
  1117.     {
  1118.       if (GameList[i].color == neutral)
  1119.     c = 0;
  1120.       else
  1121.     c = GameList[i].color + 1;
  1122.       fprintf (fd, "%d %d %d %ld %d %d %d\n",
  1123.            GameList[i].gmove, GameList[i].score, GameList[i].depth,
  1124.            GameList[i].nodes, GameList[i].time,
  1125.            GameList[i].piece, c);
  1126.     }
  1127.   fclose (fd);
  1128.   ShowMessage ("Save done.  Press <Ret>");
  1129.   fflush (stdin);
  1130.   getchar ();
  1131. }
  1132.  
  1133. void
  1134. ListGame (void)
  1135. {
  1136.   FILE *fd;
  1137.   char fname[256];
  1138.   char *tmp;
  1139.   short i, f, t;
  1140.  
  1141.   if (tmp = getenv ("HOME"))
  1142.     strcpy (fname, tmp);
  1143.   else
  1144.     fname[0] = '\0';
  1145.   strcat (fname, "/chess.lst");
  1146.  
  1147.   if (fd = fopen (fname, "w"))
  1148.     ShowMessage ("Writing ~/chess.lst");
  1149.   else
  1150.     {
  1151.       ShowMessage ("Cannot write ~/chess.lst");
  1152.       return;
  1153.     }
  1154.  
  1155.   fprintf (fd, "\n");
  1156.   fprintf (fd, "       score  depth   nodes  time         ");
  1157.   fprintf (fd, "       score  depth   nodes  time\n");
  1158.   for (i = 1; i <= GameCnt; i++)
  1159.     {
  1160.       f = GameList[i].gmove >> 8;
  1161.       t = (GameList[i].gmove & 0xFF);
  1162.       algbr (f, t, false);
  1163.       if ((i % 2) == 0)
  1164.     fprintf (fd, "\n");
  1165.       else
  1166.     fprintf (fd, "         ");
  1167.       fprintf (fd, "%5s  %5d     %2d %7ld %5d", mvstr[0],
  1168.            GameList[i].score, GameList[i].depth,
  1169.            GameList[i].nodes, GameList[i].time);
  1170.     }
  1171.   fprintf (fd, "\n\n");
  1172.   fclose (fd);
  1173.   ShowMessage ("~/chess.lst written");
  1174. }
  1175.  
  1176. void
  1177. Undo (void)
  1178.  
  1179. /*
  1180.   Undo the most recent half-move.
  1181. */
  1182.  
  1183. {
  1184.   short f, t;
  1185.   f = GameList[GameCnt].gmove >> 8;
  1186.   t = GameList[GameCnt].gmove & 0xFF;
  1187.   if (board[t] == king && distance (t, f) > 1)
  1188.     (void) castle (GameList[GameCnt].color, f, t, 2);
  1189.   else
  1190.     {
  1191.       /* Check for promotion: */
  1192.       if ((color[t] == white && row (f) == 6 && row (t) == 7)
  1193.       || (color[t] == black && row (f) == 1 && row (t) == 0))
  1194.     {
  1195.       int g, from = f;
  1196.       for (g = GameCnt - 1; g > 0; g--)
  1197.         if (GameList[g].gmove & 0xFF == from)
  1198.           from = GameList[g].gmove >> 8;
  1199.       if ((color[t] == white && row (from) == 1)
  1200.           || (color[t] == black && row (from) == 6))
  1201.         board[t] = pawn;
  1202.     }
  1203.       board[f] = board[t];
  1204.       color[f] = color[t];
  1205.       board[t] = GameList[GameCnt].piece;
  1206.       color[t] = GameList[GameCnt].color;
  1207.       if (color[t] != neutral)
  1208.     Mvboard[t]--;
  1209.       Mvboard[f]--;
  1210.     }
  1211.   if (TCflag)
  1212.     ++TimeControl.moves[color[f]];
  1213.   GameCnt--;
  1214.   computer = otherside[computer];
  1215.   opponent = otherside[opponent];
  1216.   flag.mate = false;
  1217.   Sdepth = 0;
  1218.   UpdateDisplay (0, 0, 1, 0);
  1219.   InitializeStats ();
  1220. }
  1221.  
  1222. void
  1223. ChangeAlphaWindow (void)
  1224. {
  1225.   ShowMessage ("Awindow= ");
  1226.   scanz ("%hd", &Awindow);
  1227. }
  1228.  
  1229. void
  1230. ChangeBetaWindow (void)
  1231. {
  1232.   ShowMessage ("Bwindow= ");
  1233.   scanz ("%hd", &Bwindow);
  1234. }
  1235.  
  1236. void
  1237. GiveHint (void)
  1238. {
  1239.   char s[40];
  1240.   algbr ((short) (hint >> 8), (short) (hint & 0xFF), false);
  1241.   strcpy (s, "try ");
  1242.   strcat (s, mvstr[0]);
  1243.   ShowMessage (s);
  1244. }
  1245.  
  1246. void
  1247. ChangeSearchDepth (void)
  1248. {
  1249.   ShowMessage ("depth= ");
  1250.   scanz ("%hd", &MaxSearchDepth);
  1251. }
  1252.  
  1253. void
  1254. SetContempt (void)
  1255. {
  1256.   ShowMessage ("contempt= ");
  1257.   scanz ("%hd", &contempt);
  1258. }
  1259.  
  1260. void
  1261. ChangeXwindow (void)
  1262. {
  1263.   ShowMessage ("xwndw= ");
  1264.   scanz ("%hd", &xwndw);
  1265. }
  1266.  
  1267. void
  1268. SelectLevel (void)
  1269. {
  1270.   ClrScreen ();
  1271.   gotoXY (32, 2);
  1272.   printz ("CHESS");
  1273.   gotoXY (20, 4);
  1274.   printz (" 1.   60 moves in   5 minutes");
  1275.   gotoXY (20, 5);
  1276.   printz (" 2.   60 moves in  15 minutes");
  1277.   gotoXY (20, 6);
  1278.   printz (" 3.   60 moves in  30 minutes");
  1279.   gotoXY (20, 7);
  1280.   printz (" 4.   40 moves in  30 minutes");
  1281.   gotoXY (20, 8);
  1282.   printz (" 5.   40 moves in  60 minutes");
  1283.   gotoXY (20, 9);
  1284.   printz (" 6.   40 moves in 120 minutes");
  1285.   gotoXY (20, 10);
  1286.   printz (" 7.   40 moves in 240 minutes");
  1287.   gotoXY (20, 11);
  1288.   printz (" 8.    1 move  in  15 minutes");
  1289.   gotoXY (20, 12);
  1290.   printz (" 9.    1 move  in  60 minutes");
  1291.   gotoXY (20, 13);
  1292.   printz ("10.    1 move  in 600 minutes");
  1293.  
  1294.   OperatorTime = 1;
  1295.   TCmoves = 60;
  1296.   TCminutes = 5;
  1297.  
  1298.   gotoXY (20, 17);
  1299.   printz ("Enter Level: ");
  1300.   refresh ();
  1301.   scanz ("%ld", &Level);
  1302.   switch ((int) Level)
  1303.     {
  1304.     case 1:
  1305.       TCmoves = 60;
  1306.       TCminutes = 5;
  1307.       break;
  1308.     case 2:
  1309.       TCmoves = 60;
  1310.       TCminutes = 15;
  1311.       break;
  1312.     case 3:
  1313.       TCmoves = 60;
  1314.       TCminutes = 30;
  1315.       break;
  1316.     case 4:
  1317.       TCmoves = 40;
  1318.       TCminutes = 30;
  1319.       break;
  1320.     case 5:
  1321.       TCmoves = 40;
  1322.       TCminutes = 60;
  1323.       break;
  1324.     case 6:
  1325.       TCmoves = 40;
  1326.       TCminutes = 120;
  1327.       break;
  1328.     case 7:
  1329.       TCmoves = 40;
  1330.       TCminutes = 240;
  1331.       break;
  1332.     case 8:
  1333.       TCmoves = 1;
  1334.       TCminutes = 15;
  1335.       break;
  1336.     case 9:
  1337.       TCmoves = 1;
  1338.       TCminutes = 60;
  1339.       break;
  1340.     case 10:
  1341.       TCmoves = 1;
  1342.       TCminutes = 600;
  1343.       break;
  1344.     }
  1345.  
  1346.   TCflag = (TCmoves > 1);
  1347.   SetTimeControl ();
  1348.   ClrScreen ();
  1349.   UpdateDisplay (0, 0, 1, 0);
  1350. }
  1351.  
  1352. void
  1353. DoDebug (void)
  1354. {
  1355.   short c, p, sq, tp, tc, tsq, score;
  1356.   char s[40];
  1357.   
  1358.   ExaminePosition ();
  1359.   ShowMessage ("Enter piece: ");
  1360.   scanz ("%s", s);
  1361.   c = neutral;
  1362.   if (s[0] == 'w' || s[0] == 'W')
  1363.     c = white;
  1364.   if (s[0] == 'b' || s[0] == 'B')
  1365.     c = black;
  1366.   for(p = king; p > no_piece; p--)
  1367.     if ((s[1] == pxx[p]) || (s[1] == qxx[p]))
  1368.       break;
  1369.   for (sq = 0; sq < 64; sq++)
  1370.     {
  1371.       tp = board[sq];
  1372.       tc = color[sq];
  1373.       board[sq] = p;
  1374.       color[sq] = c;
  1375.       tsq = PieceList[c][1];
  1376.       PieceList[c][1] = sq;
  1377.       ShowPostnValue (sq);
  1378.       PieceList[c][1] = tsq;
  1379.       board[sq] = tp;
  1380.       color[sq] = tc;
  1381.     }
  1382.   ScorePosition (opponent, &score);
  1383.   ShowScore (score);
  1384. }
  1385.  
  1386. void
  1387. TestSpeed(void (*f) (short int side, short int ply))
  1388. {
  1389.   short i;
  1390.   long t1, t2;
  1391.  
  1392.   t1 = time (0);
  1393.   for (i = 0; i < 10000; i++)
  1394.     {
  1395.       f (opponent, 2);
  1396.     }
  1397.   t2 = time (0);
  1398.   NodeCnt = 10000L * (TrPnt[3] - TrPnt[2]);
  1399.   evrate = NodeCnt / (t2 - t1);
  1400.   ShowNodeCnt (NodeCnt, evrate);
  1401. }
  1402.  
  1403. void
  1404. InputCommand (void)
  1405.  
  1406. /*
  1407.   Process the users command. If easy mode is OFF (the computer is thinking
  1408.   on opponents time) and the program is out of book, then make the 'hint'
  1409.   move on the board and call SelectMove() to find a response. The user
  1410.   terminates the search by entering ^C (quit siqnal) before entering a
  1411.   command. If the opponent does not make the hint move, then set Sdepth to
  1412.   zero.
  1413. */
  1414.  
  1415. {
  1416.   short ok, tmp;
  1417.   unsigned short mv;
  1418.   char s[80];
  1419.  
  1420.   ok = flag.quit = false;
  1421.   player = opponent;
  1422.   ShowSidetomove ();
  1423.   ft = 0;
  1424.   if (hint > 0 && !flag.easy && Book == NULL)
  1425.     {
  1426.       fflush (stdout);
  1427.       time0 = time ((long *) 0);
  1428.       algbr ((short) hint >> 8, (short) hint & 0xFF, false);
  1429.       strcpy (s, mvstr[0]);
  1430.       tmp = epsquare;
  1431.       if (VerifyMove (s, 1, &mv))
  1432.     {
  1433.       ShowPrompt ();
  1434.       SelectMove (computer, 2);
  1435.       (void) VerifyMove (mvstr[0], 2, &mv);
  1436.       if (Sdepth > 0)
  1437.         Sdepth--;
  1438.     }
  1439.       ft = time ((long *) 0) - time0;
  1440.       epsquare = tmp;
  1441.     }
  1442.   signal (SIGINT, Die);
  1443. #ifndef MSDOS
  1444.   signal (SIGQUIT, Die);
  1445. #endif /* MSDOS */
  1446.   while (!(ok || flag.quit))
  1447.     {
  1448.       ShowPrompt ();
  1449.       scanz ("%s", s);
  1450.       player = opponent;
  1451.       ok = VerifyMove (s, 0, &mv);
  1452.       if (ok && mv != hint)
  1453.     {
  1454.       Sdepth = 0;
  1455.       ft = 0;
  1456.     }
  1457.       if (*s == '\0')
  1458.     UpdateDisplay (0, 0, 1, 0);
  1459.       if (strcmp (s, "bd") == 0)
  1460.     {
  1461.       ClrScreen ();
  1462.       UpdateDisplay (0, 0, 1, 0);
  1463.     }
  1464.       if ((strcmp (s, "quit") == 0) || (strcmp (s, "exit") == 0))
  1465.     flag.quit = true;
  1466.       if (strcmp (s, "post") == 0)
  1467.     flag.post = !flag.post;
  1468.       if (strcmp (s, "edit") == 0)
  1469.     EditBoard ();
  1470.       if (strcmp (s, "go") == 0)
  1471.     ok = true;
  1472.       if (strcmp (s, "help") == 0)
  1473.     help ();
  1474.       if (strcmp (s, "force") == 0)
  1475.     flag.force = !flag.force;
  1476.       if (strcmp (s, "book") == 0)
  1477.     Book = NULL;
  1478.       if (strcmp (s, "undo") == 0 && GameCnt > 0)
  1479.     Undo ();
  1480.       if (strcmp (s, "new") == 0)
  1481.     NewGame ();
  1482.       if (strcmp (s, "list") == 0)
  1483.     ListGame ();
  1484.       if (strcmp (s, "level") == 0)
  1485.     SelectLevel ();
  1486.       if (strcmp (s, "hash") == 0)
  1487.     flag.hash = !flag.hash;
  1488.       if (strcmp (s, "beep") == 0)
  1489.     flag.beep = !flag.beep;
  1490.       if (strcmp (s, "Awindow") == 0)
  1491.     ChangeAlphaWindow ();
  1492.       if (strcmp (s, "Bwindow") == 0)
  1493.     ChangeBetaWindow ();
  1494.       if (strcmp (s, "hint") == 0)
  1495.     GiveHint ();
  1496.       if (strcmp (s, "both") == 0)
  1497.     {
  1498.       flag.bothsides = !flag.bothsides;
  1499.       Sdepth = 0;
  1500.       SelectMove (opponent, 1);
  1501.       ok = true;
  1502.     }
  1503.       if (strcmp (s, "reverse") == 0)
  1504.     {
  1505.       flag.reverse = !flag.reverse;
  1506.       ClrScreen ();
  1507.       UpdateDisplay (0, 0, 1, 0);
  1508.     }
  1509. #if !defined(MSDOS) || defined(SEVENBIT)
  1510.       if (strcmp (s, "shade") == 0)
  1511.     {
  1512.       shade = !shade;
  1513.       ClrScreen ();
  1514.       UpdateDisplay (0, 0, 1, 0);
  1515.     }
  1516. #endif /* MSDOS && !SEVENBIT */
  1517.       if (strcmp (s, "switch") == 0)
  1518.     {
  1519.       computer = otherside[computer];
  1520.       opponent = otherside[opponent];
  1521.       flag.force = false;
  1522.       Sdepth = 0;
  1523.       ok = true;
  1524.     }
  1525.       if (strcmp (s, "white") == 0)
  1526.     {
  1527.       computer = white;
  1528.       opponent = black;
  1529.       ok = true;
  1530.       flag.force = false;
  1531.       Sdepth = 0;
  1532.     }
  1533.       if (strcmp (s, "black") == 0)
  1534.     {
  1535.       computer = black;
  1536.       opponent = white;
  1537.       ok = true;
  1538.       flag.force = false;
  1539.       Sdepth = 0;
  1540.     }
  1541.       if (strcmp (s, "remove") == 0 && GameCnt > 1)
  1542.     {
  1543.       Undo ();
  1544.       Undo ();
  1545.     }
  1546.       if (strcmp (s, "get") == 0)
  1547.     GetGame ();
  1548.       if (strcmp (s, "save") == 0)
  1549.     SaveGame ();
  1550.       if (strcmp (s, "depth") == 0)
  1551.     ChangeSearchDepth ();
  1552.       if (strcmp (s, "random") == 0)
  1553.     dither = 6;
  1554.       if (strcmp (s, "easy") == 0)
  1555.     flag.easy = !flag.easy;
  1556.       if (strcmp (s, "contempt") == 0)
  1557.     SetContempt ();
  1558.       if (strcmp (s, "xwndw") == 0)
  1559.     ChangeXwindow ();
  1560.       if (strcmp (s, "coords") == 0)
  1561.     {
  1562.       coords = !coords;
  1563.       UpdateDisplay (0, 0, 1, 0);
  1564.     }
  1565. #if !defined(MSDOS) || defined(SEVENBIT)
  1566.       if (strcmp (s, "stars") == 0)
  1567.     {
  1568.       stars = !stars;
  1569.       UpdateDisplay (0, 0, 1, 0);
  1570.     }
  1571. #endif /* MSDOS && !SEVENBIT */
  1572.       if (strcmp (s, "test") == 0)
  1573.     {
  1574.           ShowMessage("Testing MoveList Speed");
  1575.       TestSpeed (MoveList);
  1576.           ShowMessage("Testing CaptureList Speed");
  1577.       TestSpeed (CaptureList);
  1578.     }
  1579.       if (strcmp (s, "p") == 0)
  1580.     ShowPostnValues ();
  1581.       if (strcmp (s, "debug") == 0)
  1582.     DoDebug ();
  1583.       if (strcmp (s, "rv") == 0)
  1584.     {
  1585.       rv = !rv;
  1586. #if !defined(MSDOS) || defined(SEVENBIT)
  1587.       shade = !rv;
  1588.       stars = !rv;
  1589. #endif /* MSDOS && !SEVENBIT */
  1590.       UpdateDisplay (0, 0, 1, 0);
  1591.     }
  1592.     }
  1593.  
  1594.   ClearMessage ();
  1595.   ElapsedTime (1);
  1596.   if (flag.force)
  1597.     {
  1598.       computer = opponent;
  1599.       opponent = otherside[computer];
  1600.     }
  1601.   signal (SIGINT, TerminateSearch);
  1602. #ifndef MSDOS
  1603.   signal (SIGQUIT, TerminateSearch);
  1604. #endif /* MSDOS */
  1605. }
  1606.